// 本可执行程序接收登录请求
// 需要连接数据库


/*
数据库的名字为： Web_game
数据库中的表结构为：

CREATE TABLE player_information 
(
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(50) NOT NULL,
    points INT
);

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int         | NO   | PRI | NULL    | auto_increment |
| username | varchar(50) | NO   |     | NULL    |                |
| password | varchar(50) | NO   |     | NULL    |                |
| points   | int         | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+


*/


/*

函数原型：

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, 
const char *passwd, const char *db, unsigned int port, 
const char *unix_socket, unsigned long client_flag);

参数说明：
mysql：一个指向已初始化的 MYSQL 结构体的指针。
host：MySQL 服务器的主机名或 IP 地址。
user：连接 MySQL 服务器的用户名。
passwd：连接 MySQL 服务器的密码。
db：要连接的数据库名称。
port：MySQL 服务器的端口号。
unix_socket：UNIX 套接字路径（通常用于本地连接）。
client_flag：客户端标志，用于指定连接选项。

返回值：
如果连接成功，则返回一个指向 MYSQL 结构体的指针，表示连接句柄。
如果连接失败，则返回 NULL，并可以使用 mysql_error() 函数获取错误信息。

*/

#include <string> 
#include <mysql/mysql.h>
#include <iostream>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


#include "game_log_server.hpp"
#define ACOUNT_NAME  "player_information"
#define WEB_PAGE_PATH "/root/temp/item2.0/wwwroot/game.html"
#define MAX_PAGE_SIZE 1024

// 账号、密码验证成功后返回一个固定前端页面
// 返回方法1
bool mySendFilePacked()
{
    struct stat a;
    stat(WEB_PAGE_PATH, &a);
    int  web_size = a.st_size ; 
    int web_fd = open(WEB_PAGE_PATH, O_RDONLY) ;
    
    if(sendfile(1, web_fd, NULL, web_size) > 0) 
    {
        std::cerr << "mySendFilePacked() send web success" << std::endl ;
    }
    else
    {
        std::cerr << "mySendFilePacked() send web failed" << std::endl ;
    }

    close(web_fd) ; 
}

// 将指定文件的内容，写入指定文件描述符
// 返回方法2
void writeFileContentToFD(const std::string& filename = WEB_PAGE_PATH, int fd = 1) 
{
    int web_page_fd = open(filename.c_str(), O_RDONLY) ;

    if (web_page_fd == -1) 
    {
        std::cerr << "open";
        return ;
    }

    char buffer[MAX_PAGE_SIZE] ; 
    ssize_t real_size = read(web_page_fd, buffer, sizeof(buffer)) ;

    std::cerr << "had read content size:" << std::to_string(real_size) << std::endl ;

    write(1, buffer, MAX_PAGE_SIZE) ; 
    
    close(web_page_fd) ; 
}


// 实现CGI功能: 验证账号密码, 并返回验证成功的页面
int main() 
{

    /*
    
MYSQL 是 MySQL C API 中定义的一个结构体，代表一个 MySQL 连接。
conn 是一个指向 MYSQL 结构体的指针，用于表示与 MySQL 服务器的连接。
通常在使用 MySQL C API 时，首先需要声明一个 MYSQL * 类型的指针变量，用于存储连接句柄。
MYSQL_RES *res;：

MYSQL_RES 是 MySQL C API 中定义的一个结构体，代表一个查询结果集。
res 是一个指向 MYSQL_RES 结构体的指针，用于存储查询结果集。
当执行查询语句后，查询结果将会存储在 MYSQL_RES 结构体中，通过 res 指针可以访问和处理查询结果。
MYSQL_ROW row;：

MYSQL_ROW 是 MySQL C API 中定义的一个类型，通常用于表示查询结果集中的一行数据。
row 是一个 MYSQL_ROW 类型的变量，用于存储查询结果集中的一行数据。
当使用 mysql_fetch_row 函数从查询结果集中获取一行数据时，会将该行数据存储在 row 中，可以通过 row 访问该行数据的各个字段。
    
    */

   std::string adjust_account  ;
   std::string adjust_password ; 

    // 从环境变量中获取参数
    if(getAcountNumberAndPassword(adjust_account, adjust_password) == false )
    {
        std::cerr << "getAcountNumberAndPassword failed" << std::endl ; 
    }

    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 初始化连接句柄
    conn = mysql_init(NULL);

    if (conn == NULL) 
    {
        std::cerr << "mysql_init() failed" << std::endl;
        return 1;
    }

    // 目前没设置密码
    // "localhost" 代表本机数据库 IP 127.0.0.1
    conn = mysql_real_connect(conn, "localhost", "root", "password", "Web_game", 3306, NULL, 0);

    if (conn == NULL) 
    {
        std::cerr << "mysql_real_connect() failed" << std::endl;
        return 1;
    }
    else
    {
        std::cerr <<  conn->host << " " ; 
    }

    if (mysql_query(conn, "SELECT * FROM player_information ")) 
    {
        std::cerr << "mysql_query() failed" << std::endl;
        return 1;
    }

    res = mysql_store_result(conn);


    //用于验证账号密码是否匹配成功
    bool falg  =  false ; 
    //逐行获取查询结果集中的数据。
    while ((row = mysql_fetch_row(res))) 
    {
        std::string mysql_account(row[0]) ; 
        std::string mysql_password(row[2]) ;

        if(adjust_account == mysql_account 
        && adjust_password == mysql_password)
        {
            // 返回登入成功后，返回的前端页面
            //writeFileContentToFD() ; 
            mySendFilePacked() ; 
            falg = true ; 
        }
    }

    if(falg == false) 
    {
        // 验证失败 
        std::cerr << "account or passwprd is incorrect " << std::endl ;
    }

    mysql_free_result(res);
    mysql_close(conn);

    return 0;
}